/**
	License:		Artistic license 2.0 (see license.txt, also available online at http://www.perlfoundation.org/artistic_license_2_0)
	Authors:		OrbitalLab (http://www.orbitallab.ru/moonglide/), 2007-2009

	File:			AnimPlanet.d
	Description:	planet`s animator
	Date:			16.07.2008 by Jurec
**/
module client.customscenes.demoscene.AnimPlanet;

import 	MoonGlide,
		moonglide.core.engobjects.EngGeometry;



//=============================================================
/// Planet animator
//=============================================================
class CAnimPlanet : IAnimator
{
	mixin TEventGenerator;

	protected:
		float		_curSelfRot = 0,
					_curParRot = 0;
		Vector3f	_pos;
	public:
		CEngGeometry	parent;

		float		selfRot,
					parRot;

		void animate( float time )
		{
			_curSelfRot += selfRot * time;
			_curParRot += parRot * time;

			parent.position = Matrix33f.rotationY( _curParRot ) * _pos;
			parent.orientation = Matrix33f.rotationY( -_curSelfRot );

			SShaderLoc* loc;
			loc = parent.material.shader.getLocalByName( "tesst", sh_Fragment );

			if( loc )
			{
				loc.setData( Vector4f(sin(_curSelfRot), 1- _curSelfRot , time, 1 ) );
			}

	//		loc = parent.material.shader.getLocalByNum( "abc" );
			//if( loc )
			//	loc.setData( _curSelfRot );
		}

		//================================================================
		/// callback: getting todo-data
		//================================================================
		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			//
		}

		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}

		//================================================================
		/// constructor & destructor
		//================================================================
		this( CEngGeometry obj )
		{
			parent = obj;
			_id = parent.id ~ "_plananim";
			_pos = parent.position;
		}

		~this()
		{
			parent = null;
		}
}

class CCameraSpec : IAnimator
{
	mixin TEventGenerator;

	public:
		CEngObject	spec;
		CEngCamera  parent;

        Vector3f camLocalPos;

		void animate( float time )
		{
		    Matrix33f mat = spec.orientation;
		    mat.transpose;

		    parent.orientation = mat*Matrix33f.rotationY(PI);
			parent.position = (mat*camLocalPos) + spec.position;
		}

		//================================================================
		/// callback: getting todo-data
		//================================================================
		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			//
		}

		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}

		//================================================================
		/// constructor & destructor
		//================================================================
		this( CEngCamera par, CEngObject spe )
		{
			parent = par;
			spec = spe;
			_id = parent.id ~ "_specanim";

			camLocalPos = par.position;
		}

		~this()
		{

		}
}

//=============================================================
/// Ship animator
//=============================================================
//class CAnimShip : IAnimator
//{
//	mixin TEventGenerator;
//
//	protected:
//		CEngObject	_parent;
//		CEvent		_event;
//
//		//================================================================
//		/// get accels data from controller states
//		//================================================================
//		void getMoveData( )
//		{
//			if( keyboardState[ 87 ] )
//				aimRotateAngles.y = 0.04f;
//			else
//				if( keyboardState[ 83 ] )
//					aimRotateAngles.y = -0.04f;
//				else
//					aimRotateAngles.y = 0.0f;
//
//			if( keyboardState[65] )
//				aimRotateAngles.x = 0.04f;
//			else
//				if( keyboardState[68] )
//					aimRotateAngles.x = -0.04f;
//				else
//					aimRotateAngles.x = 0.0f;
//
//			if( keyboardState[69] )
//				aimRotateAngles.z = 0.04f;
//			else
//				if( keyboardState[81] )
//					aimRotateAngles.z = -0.04f;
//				else
//					aimRotateAngles.z = 0.0f;
//
//			if( keyboardState[186] )
//				aimMove = 5f;
//			else
//				if( keyboardState[191] )
//					aimMove = -5f;
//				else
//					aimMove = 0.0;
//
//		}
////========================================================
//
//	public:
//		Vector3f
//			aimRotateAngles;
//
//		float aimMove = 0.0f;
//
//		Vector3f
//			moving,
//			tmpVector,
//			aimSpeed,
//			speed;
//
//		Quaternion
//			rotNow;
//
//		Matrix33f
//			orientation,
//			rotationMatrix;
//
//			//================================================================
//		/// main processing
//		//================================================================
//		void animate( float time )
//		{
//			moonAssert( time > 0, "", __FILE__, __LINE__ );
//
//			getMoveData; // check mouse and kb state
//
//			float coef =  0.15 * time;
//
//
//			Quaternion res = Quaternion.rotation( aimRotateAngles.x, aimRotateAngles.y, aimRotateAngles.z );
//			rotNow = slerp2( rotNow, res, coef );
//			rotNow.normalize;
//
//			_parent.orientation =  Matrix33f.rotation( rotNow ) * _parent.orientation;
//			_parent.orientation.ortNormalize;
//
//
//			Vector3f tmpVector;
//			tmpVector.set( _parent.worientation[2, 0], _parent.worientation[2, 1], _parent.worientation[2, 2] );
//
//			aimSpeed = tmpVector * aimMove;
//
//			speed.x = moonglide.math.Basic.lerp( speed.x, aimSpeed.x, coef );
//			speed.y = moonglide.math.Basic.lerp( speed.y, aimSpeed.y, coef );
//			speed.z = moonglide.math.Basic.lerp( speed.z, aimSpeed.z, coef );
//
//			_parent.position += speed;
//		}
//
//		//================================================================
//		/// callback: getting todo-data
//		//================================================================
//		void onEventCallback( CEvent event, IEventGenerator gen )
//		{
//			//
//		}
//
//		void onEventReceive( CEvent event, IEventSender sender )
//		{
//			//
//		}
//
//
//		//================================================================
//		/// constructor with initializing
//		//================================================================
//		this( CEngObject obj )
//		{
//			rotNow = Quaternion.rotationY( 0 );
//			_parent = obj;
//
//			_id = _parent.id ~ "_shanim";
//
//			_event = new CEvent( eeventtype.program, eprogramevent.command );
//		}
//
//		~this()
//		{
//			_parent = null;
//		}
//}



//=============================================================
/// Rocket animator
//=============================================================
class CRockAnim : IAnimator
{
	mixin TEventGenerator;

	protected:
		CEngObject	_parent,_aim;
		CEvent		_event;
	public:
		Vector3f
			aimPos,
			aimSpeed,
			Speed;

		float aimMove = 0.0f;

		void lookAt(Vector3f pos)
		{
			Vector3f z1, z2;
			z1 = _parent.wposition - pos;
			z1.normalize;

			z2.set( _parent.orientation[2, 0], _parent.orientation[2, 1], _parent.orientation[2, 2] );

			if( dp( z1, z2 ) < -(1-0.025/2) )
				return;

			Quaternion qua;

			float coef = 0.97f;

			qua = shortestArc(z1,z2);
			qua = fastslerp( qua, coef );
			qua.normalize;

			_parent.orientation = _parent.orientation * Matrix33f.rotation(qua);
		}

		//================================================================
		/// main processing
		//================================================================
		void animate( float time )
		{
			moonAssert( time > 0, "", __FILE__, __LINE__ );

			float coef = 0.001 * time;


			if( _aim )
				lookAt( _aim.wposition );


			Vector3f tmpVector = Vector3f( _parent.worientation[2, 0], _parent.worientation[2, 1], _parent.worientation[2, 2] );

			aimSpeed = tmpVector * 1.5;

			Speed.x = moonglide.math.Basic.lerp( Speed.x, aimSpeed.x, coef );
			Speed.y = moonglide.math.Basic.lerp( Speed.y, aimSpeed.y, coef );
			Speed.z = moonglide.math.Basic.lerp( Speed.z, aimSpeed.z, coef );

			_parent.position += Speed;
		}

		//================================================================
		/// callback: getting todo-data
		//================================================================
		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			//
		}

		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}


		//================================================================
		/// constructor with initializing
		//================================================================
		this( CEngObject obj, CEngObject aim = null )
		{
			_aim = aim;
			_parent = obj;

			_id = _parent.id ~ "_roanim";

			_event = new CEvent( eeventtype.program, eprogramevent.command );
		}

		~this()
		{
			_parent = null;
		}
}



//=============================================================
/// move animator
//=============================================================
class CMoveAnim : IAnimator
{
	mixin TEventGenerator;

	protected:
		CEngObject	_parent;
		CEvent		_event;
	public:
        Vector3f MovSpeed;

		//================================================================
		/// main processing
		//================================================================
		void animate( float time )
		{
			moonAssert( time > 0, "", __FILE__, __LINE__ );

			float coef = time;

			_parent.position += MovSpeed * coef;
		}

		//================================================================
		/// callback: getting todo-data
		//================================================================
		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			//
		}

		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}


		//================================================================
		/// constructor with initializing
		//================================================================
		this( CEngObject obj, float Xsp = 0.05f, float Ysp =0, float Zsp = 0 )
		{
			_parent = obj;
			MovSpeed.set( Xsp,Ysp,Zsp );

			_id = _parent.id ~ "_MoVanim";

			_event = new CEvent( eeventtype.program, eprogramevent.command );
		}

		~this()
		{
			_parent = null;
		}
}


//=============================================================
/// rotator animator
//=============================================================
class CRotAnim : IAnimator
{
	mixin TEventGenerator;

	protected:
		CEngObject	_parent;
		CEvent		_event;
	public:
        Vector3f RotSpeed;
        Vector3f angl;

		//================================================================
		/// main processing
		//================================================================
		void animate( float time )
		{
			moonAssert( time > 0, "", __FILE__, __LINE__ );

			float coef = time;

			while( angl.x > 2*PI ) angl.x -= 2*PI;
			while( angl.y > 2*PI ) angl.y -= 2*PI;
			while( angl.z > 2*PI ) angl.z -= 2*PI;

			angl += coef * RotSpeed;

			_parent.orientation = Matrix33f.rotation(angl.x,angl.y,angl.z);
		}

		//================================================================
		/// callback: getting todo-data
		//================================================================
		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			//
		}

		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}


		//================================================================
		/// constructor with initializing
		//================================================================
		this( CEngObject obj, float Xsp = 0.05f, float Ysp =0, float Zsp = 0 )
		{
			_parent = obj;
			RotSpeed.set( Xsp,Ysp,Zsp );

			_id = _parent.id ~ "_Zanim";

			_event = new CEvent( eeventtype.program, eprogramevent.command );
		}

		~this()
		{
			_parent = null;
		}
}


//=============================================================
/// scale animator
//=============================================================
class CScaleAnim : IAnimator
{
	mixin TEventGenerator;

	protected:
		CEngObject	_parent;
		CEvent		_event;
	public:
        Vector3f scaSpeed;
        Vector3f maxSca;
        Vector3f angl;

		//================================================================
		/// main processing
		//================================================================
		void animate( float time )
		{
			moonAssert( time > 0, "", __FILE__, __LINE__ );

			float coef = time;

            (cast(CEngGeometry)_parent).material.vectors4["color"] = Vector4f(
                    (maxSca.x - angl.x) / maxSca.x,
                    (maxSca.y - angl.y) / maxSca.y,
                    (maxSca.z - angl.z) / maxSca.z, 1.f) * 0.5;

			angl += coef * scaSpeed;
			if ((angl.x > maxSca.x) || (angl.y > maxSca.y) || (angl.z > maxSca.z))
			{
			    angl.set(0.f,0.f,0.f);

			}


			_parent.orientation = Matrix33f.scale(angl.x,angl.y,angl.z);
		}

		//================================================================
		/// callback: getting todo-data
		//================================================================
		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			//
		}

		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}


		//================================================================
		/// constructor with initializing
		//================================================================
		this( CEngObject obj, float Xsp = 0.05f, float Ysp = 0.05f, float Zsp = 0.05f )
		{
			_parent = obj;
			scaSpeed.set( Xsp,Ysp,Zsp );
			maxSca.set(1.f,1.f,1.f);

			_id = _parent.id ~ "_ScaAnim";

			_event = new CEvent( eeventtype.program, eprogramevent.command );
		}

		~this()
		{
			_parent = null;
		}
}

//=============================================================
/// lod animator
//=============================================================
class CLodAnim : IAnimator
{
	mixin TEventGenerator;

	protected:
		CEngGeometry	_parent;
		CResTextureData _tex;
		CEngCamera      _cam;
		float           _count = 0;
	public:
	    //================================================================
		/// main processing
		//================================================================
		void animate( float time )
		{
			moonAssert( time > 0, "", __FILE__, __LINE__ );
			_count += time;

			if( _count > 1000.5)
			{
                _count = 0;
                _parent.clearLods;
                _parent.addLod( genMeshByTexture(_tex, cast(int)(_cam.wposition.x/10), cast(int)(_cam.wposition.y/10)) , 0 );
			}
		}

		//================================================================
		/// callback: getting todo-data
		//================================================================
		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			//
		}

		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}


		//================================================================
		/// constructor with initializing
		//================================================================
		this( CEngGeometry obj, CResTextureData tex, CEngCamera cam )
		{
			_parent = obj;
			_tex = tex;
			_cam = cam;

			_id = _parent.id ~ "_Lodanim";

		}

		~this()
		{
			_parent = null;
		}
}

/*
class CParticleDust : public CEngParSystem
{
	public:
		override void update( float timeelapsed, ref Vector3f parentWPos, ref Matrix33f parentWOrient )
		{
			if( !needUpdate )
				return;

			updateAnimators( timeelapsed );

			worientation = orientation;
			wposition = position;

			visible(( disToCam >= floats["begVis"]-10 ) && ( disToCam < floats["endVis"] ));

			foreach( inout child; children )
				child.update( timeelapsed, wposition, worientation );
		}
}
*/
